package com.slmxz.tms.core.aspect;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TimeInterval;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil;
import cn.hutool.json.JSONUtil;
import com.slmxz.tms.common.enums.LogModuleEnum;
import com.slmxz.tms.system.model.entity.Log;
import com.slmxz.tms.system.service.LogService;
import com.slmxz.tms.common.component.PrimaryKeyGeneratorService;
import com.slmxz.tms.common.constant.SecurityConstants;
import com.slmxz.tms.common.enums.TableEnum;
import com.slmxz.tms.common.util.IPUtils;
import com.slmxz.tms.core.security.util.SecurityUtils;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

/**
 * 日志切面
 * @author sunyao
 * @Date 2024-12-01
 */
@Aspect
@Component
@RequiredArgsConstructor
@Slf4j
public class LogAspect {

    private final LogService logService;
    private final HttpServletRequest request;

    @Pointcut("@annotation(com.slmxz.tms.common.annotation.Log)")
    public void logPointcut() {
    }

    @Around("logPointcut() && @annotation(logAnnotation)")
    public Object logExecutionTime(ProceedingJoinPoint joinPoint, com.slmxz.tms.common.annotation.Log logAnnotation) throws Throwable {
        String requestURI = request.getRequestURI();

        Long userId = null;
        // 非登录请求获取用户ID，登录请求在登录成功后(joinPoint.proceed())获取用户ID
        if (!SecurityConstants.LOGIN_PATH.equals(requestURI)) {
            userId = SecurityUtils.getUserId();
        }

        TimeInterval timer = DateUtil.timer();
        // 执行方法
        Object proceed = joinPoint.proceed();
        long executionTime = timer.interval();

        // 创建日志记录
        Log log = new Log();
        log.setModule(logAnnotation.module().getModuleName());
        //获取接口请求参数
        Object[] args = joinPoint.getArgs();
        // 登录方法的参数是用户名和密码，不记录密码
        if (logAnnotation.module() == LogModuleEnum.LOGIN) {
            args = new Object[]{""};
        }
        String content = JSONUtil.toJsonStr(args);
        if(StrUtil.isNotBlank(content) && content.length() > 2000){
            content = content.substring(0,2000); //数据库内容不能无限大,默认只保存2000
        }
        log.setContent(content);
        log.setOperateItem(logAnnotation.value());
        log.setRequestUri(requestURI);
        // 登录方法需要在登录成功后获取用户ID
        if (userId == null) {
            userId = SecurityUtils.getUserId();
        }
        log.setCreateBy(userId);
        String ipAddr = IPUtils.getIpAddr(request);
        if (StrUtil.isNotBlank(ipAddr)) {
            log.setIp(ipAddr);
            String region = IPUtils.getRegion(ipAddr);
            // 中国|0|四川省|成都市|电信 解析省和市
            if (StrUtil.isNotBlank(region)) {
                String[] regionArray = region.split("\\|");
                if (regionArray.length > 2) {
                    log.setProvince(regionArray[2]);
                    log.setCity(regionArray[3]);
                }
            }
        }
        log.setExecutionTime(executionTime);
        // 获取浏览器和终端系统信息
        String userAgentString = request.getHeader("User-Agent");
        UserAgent userAgent = UserAgentUtil.parse(userAgentString);
        // 系统信息
        log.setOs(userAgent.getOs().getName());
        // 浏览器信息
        log.setBrowser(userAgent.getBrowser().getName());
        log.setBrowserVersion(userAgent.getBrowser().getVersion(userAgentString));
        // 保存日志到数据库
        Long logId = PrimaryKeyGeneratorService.generateId(TableEnum.TABLE_LOG);
        log.setId(logId);
        logService.save(log);

        return proceed;
    }


}
